import 'package:family_expense/features/journey/models/journey.dart';
import 'package:family_expense/features/journey/models/journey_income_expense_detail.dart';
import 'package:family_expense/features/journey/services/journey_income_expense_detail_service.dart';
import 'package:family_expense/features/journey/services/journey_service.dart';
import 'package:family_expense/features/journey/widgets/edit_journey.dart';
import 'package:family_expense/features/journey/widgets/edit_journey_income_expense_detail.dart';
import 'package:family_expense/features/journey/widgets/journey_income_expense_detail_shared.dart';
import 'package:family_expense/features/journey/widgets/journey_income_expense_detail_view.dart';
import 'package:family_expense/features/journey/widgets/region_shared.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

class JourneyIncomeExpenseList extends StatefulWidget {
  const JourneyIncomeExpenseList(this.journey, {super.key});

  final Journey journey;

  @override
  State<JourneyIncomeExpenseList> createState() =>
      _JourneyIncomeExpenseListState();
}

class _JourneyIncomeExpenseListState extends State<JourneyIncomeExpenseList> {
  final int _pageSize = GeneralConfig.listViewPageSize;
  final JourneyService _journeyService = JourneyService();

  final JourneyIncomeExpenseDetailService _incomeExpenseDetailService =
      JourneyIncomeExpenseDetailService();

  bool _dataUpdated = false;

  // In order to refresh the list after item changes. Including updated, added or removed.
  late PagingListViewLoadController _loadController;

  late Journey _journey = widget.journey;
  late String _keyword;

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: _onPopInvokedWithResult,
      child: Scaffold(appBar: _buildAppBar(), body: _buildBody()),
    );
  }

  PreferredSizeWidget _buildAppBar() {
    return AppBar(
      title: Row(
        children: [
          RegionFlag(_journey.region!),
          const SizedBox(width: 8.0),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(_journey.region!.title!),
              Text(
                '${_journey.startDate.formatDate(DatePatterns.longDate)} 至 ${_journey.endDate.formatDate(DatePatterns.longDate)}',
                style: const TextStyle(fontSize: 12.0),
              ),
            ],
          ),
        ],
      ),
      actions: <Widget>[
        FutureBuilder<User?>(
          future: AuthStateService.instance.currentUser,
          builder: (context, userSnapshot) => IconButton(
            icon: const Icon(Icons.more_horiz),
            onPressed: () {
              showModalBottomSheet(
                context: context,
                builder: (context) {
                  return getSelectionBottomSheetContent([
                    if (userSnapshot.data?.isViewerOnly == false)
                      ListTile(
                        leading: const Icon(Icons.add),
                        title: const Text('添加收支'),
                        onTap: () {
                          // Closes opened bottom sheet.
                          NavigatorHelper.pop(context);

                          _gotoAddIncomeExpenseView();
                        },
                      ),
                    ListTile(
                      leading: const Icon(Icons.search),
                      title: const Text('搜索收支'),
                      onTap: () {
                        // Closes opened bottom sheet.
                        NavigatorHelper.pop(context);

                        _openSearch();
                      },
                    ),
                    if (userSnapshot.data?.isViewerOnly == false)
                      ListTile(
                        leading: Icon(MdiIcons.airplaneEdit),
                        title: const Text('修改旅程'),
                        onTap: () {
                          // Closes opened bottom sheet.
                          NavigatorHelper.pop(context);

                          _gotoUpdateJourneyView();
                        },
                      ),
                    if (userSnapshot.data?.isViewerOnly == false)
                      ListTile(
                        leading: Icon(MdiIcons.delete),
                        title: const Text('删除旅程'),
                        onTap: () {
                          // Closes opened bottom sheet.
                          NavigatorHelper.pop(context);

                          _deleteJourney();
                        },
                      ),
                  ], isHoriz: false);
                },
              );
            },
          ),
        ),
      ],
    );
  }

  /// Builds main body.
  Widget _buildBody() {
    return PagingListView(
      padding: const EdgeInsets.only(top: 10.0),
      pageSize: _pageSize,
      getLoadController: (loadController) => _loadController = loadController,
      retrieveData: (pageIndex) =>
          _incomeExpenseDetailService.queryListByJourney(
            pageSize: _pageSize,
            pageIndex: pageIndex!,
            journeyId: _journey.id!,
          ),
      itemBuilder: (context, entry, index) => _buildListTile(entry),
    );
  }

  /// Builds list tile to show journey info.
  Widget _buildListTile(JourneyIncomeExpenseDetail incomeExpenseDetail) {
    return JourneyIncomeExpenseDetailListTile(incomeExpenseDetail, () async {
      final dataUpdated = await NavigatorHelper.push<bool>(
        context,
        JourneyIncomeExpenseDetailView(
          id: incomeExpenseDetail.id!,
          journey: _journey,
        ),
      );

      // If the income/expense details is updated we need to refresh the list.
      if (dataUpdated == true) {
        _loadController.reset();
      }
    });
  }

  /// Builds list tile to show journey income/expense search result.
  Widget _buildJourneyIncomeExpenseSearchResultListTile(
    JourneyIncomeExpenseDetail incomeExpenseDetail,
  ) {
    return JourneyIncomeExpenseDetailListTile(incomeExpenseDetail, () {
      NavigatorHelper.push<bool>(
        context,
        JourneyIncomeExpenseDetailView(
          id: incomeExpenseDetail.id!,
          journey: _journey,
        ),
      );
    }, keywords: _keyword.split(' '));
  }

  /// Goes to add income/expense view.
  Future<void> _gotoAddIncomeExpenseView() async {
    final dataUpdated =
        await NavigatorHelper.push<bool>(
          context,
          EditJourneyIncomeExpenseDetail(
            incomeExpenseDetail: JourneyIncomeExpenseDetail(journey: _journey),
          ),
        ) ??
        false;

    if (dataUpdated) {
      _loadController.reset();
    }
  }

  Future<void> _openSearch() async {
    showSearch<dynamic>(
      context: context,
      delegate: GeneralSearchDelegate(
        (keyword) {
          _keyword = keyword;

          return _incomeExpenseDetailService.queryListByJourney(
            pageSize: _pageSize,
            pageIndex: 0,
            journeyId: _journey.id!,
            keyword: keyword,
          );
        },
        buildSuggestionItem: (entry) =>
            _buildJourneyIncomeExpenseSearchResultListTile(entry),
      ),
    );
  }

  /// Goes to update journey view.
  Future<void> _gotoUpdateJourneyView() async {
    final result = await NavigatorHelper.push<EditJourneyResult>(
      context,
      EditJourney(journey: _journey),
    );

    if (result?.dataUpdated == true && mounted) {
      _dataUpdated = true;
      setState(() => _journey = result!.journey!);
    }
  }

  /// Deletes journey.
  Future<void> _deleteJourney() async {
    showConfirmDialog(
      context,
      '删除 ${_journey.region!.title!} 旅程？',
      onConfirm: () async {
        showInProgressOverlay(context);

        // Deletes item on back server.
        final result = await _journeyService.delete(_journey.id!);

        if (mounted) {
          // Closes progress overlay.
          NavigatorHelper.pop(context);

          // DO NOT use BuildContext across asynchronous gaps.
          // https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
          if (result) {
            // Pops detail view and notifies last page to reload.
            NavigatorHelper.pop(context, true);
          } else {
            showToast('不可以删除有收支记录的旅程');
          }
        }
      },
    );
  }

  void _onPopInvokedWithResult(bool didPop, dynamic result) {
    if (didPop) {
      return;
    }

    NavigatorHelper.pop(context, _dataUpdated);
  }
}
